/**
 * WebSocket聊天工具类
 */

import { getCurrentUserId } from './userAuth.js'
import { userApi } from '../api/user.js'

class ChatWebSocket {
  constructor() {
    this.ws = null
    this.url = 'ws://8.145.55.161:6002/chat'  // 使用6002端口，与后端配置一致
    this.reconnectInterval = 5000 // 重连间隔
    this.maxReconnectAttempts = 5 // 最大重连次数
    this.reconnectAttempts = 0
    this.messageHandlers = new Set()
    this.isManualClose = false
    this.heartbeatInterval = null // 心跳定时器
    this.heartbeatTimeout = 30000 // 心跳超时时间
    this.connectionStatus = 'disconnected' // 连接状态
    this.currentUsername = null // 当前用户名
    this.onlineUsers = new Set() // 在线用户列表
    this.onlineStatusHandlers = new Set() // 在线状态变化处理器
  }

  /**
   * 连接WebSocket
   */
  connect() {
    if (this.ws && this.ws.readyState === WebSocket.CONNECTING) {
      console.log('WebSocket正在连接中...')
      return
    }
    
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      console.log('WebSocket已连接')
      return
    }

    // 获取当前用户信息
    const userInfo = uni.getStorageSync('userInfo')
    this.currentUsername = userInfo?.username || userInfo?.nickname || userInfo?.realName
    this.currentUserId = userInfo?.id || userInfo?.userId

    if (!this.currentUsername || !this.currentUserId) {
      console.error('用户未登录或用户信息不完整，无法连接WebSocket', { username: this.currentUsername, userId: this.currentUserId })
      uni.showToast({
        title: '请先登录',
        icon: 'none'
      })
      return
    }

    console.log('当前用户:', this.currentUsername, 'ID:', this.currentUserId)

    try {
      this.connectionStatus = 'connecting'

      // 在URL中添加用户名和用户ID参数
      const connectUrl = `${this.url}?username=${encodeURIComponent(this.currentUsername)}&userId=${this.currentUserId}`
      console.log('正在连接WebSocket...', connectUrl)
      
      // 清理旧连接
      if (this.ws) {
        this.ws.close()
        this.ws = null
      }
      
      this.ws = new WebSocket(connectUrl)
      this.setupEventHandlers()
    } catch (error) {
      console.error('WebSocket连接失败:', error)
      this.connectionStatus = 'disconnected'
      this.handleReconnect()
    }
  }

  /**
   * 设置事件处理器
   */
  setupEventHandlers() {
    this.ws.onopen = () => {
      console.log('WebSocket连接成功，用户:', this.currentUsername)
      this.connectionStatus = 'connected'
      this.reconnectAttempts = 0
      this.startHeartbeat()
      this.onConnected()

      // 显示连接成功提示
      uni.showToast({
        title: '聊天连接成功',
        icon: 'success',
        duration: 1500
      })
    }

    this.ws.onmessage = (event) => {
      try {
        // 处理心跳响应
        if (event.data === 'pong') {
          console.log('收到心跳响应')
          return
        }

        const data = JSON.parse(event.data)
        console.log('WebSocket收到消息:', data)

        // 处理在线用户列表更新
        if (data.system && data.message && Array.isArray(data.message)) {
          console.log('更新在线用户列表:', data.message)
          this.updateOnlineUsers(data.message)
        }

        // 立即处理消息
        this.handleMessage(data)
      } catch (error) {
        console.error('解析WebSocket消息失败:', error, '原始数据:', event.data)
      }
    }

    this.ws.onclose = (event) => {
      const closeCode = event.code || 'unknown'
      const closeReason = event.reason || '未知原因'
      
      console.log(`WebSocket连接关闭: 代码=${closeCode}, 原因=${closeReason}`)
      
      // 特殊处理常见错误码
      if (closeCode === 1006) {
        console.warn('连接异常关闭，可能是网络问题或服务器不可达')
        uni.showToast({
          title: '连接中断，正在重连...',
          icon: 'none',
          duration: 2000
        })
      } else if (closeCode === 1000) {
        console.log('正常关闭连接')
      } else if (closeCode === 1001) {
        console.log('端点离线（例如页面关闭）')
      }
      
      this.connectionStatus = 'disconnected'
      this.stopHeartbeat()
      
      if (!this.isManualClose) {
        this.handleReconnect()
      }
    }

    this.ws.onerror = (error) => {
      console.error('WebSocket错误:', error)
      this.connectionStatus = 'error'
      
      // 显示用户友好的错误信息
      console.log('连接出现错误，请检查：')
      console.log('1. 后端服务是否正常运行在端口6002')
      console.log('2. 网络连接是否正常')
      console.log('3. 防火墙或代理设置是否屏蔽WebSocket')
    }
  }

  /**
   * 处理重连
   */
  handleReconnect() {
    if (this.isManualClose) {
      return
    }
    
    if (this.reconnectAttempts < this.maxReconnectAttempts) {
      this.reconnectAttempts++
      this.connectionStatus = 'reconnecting'
      
      // 动态调整重连间隔，逐步递增
      const delay = Math.min(this.reconnectInterval * this.reconnectAttempts, 30000)
      
      console.log(`尝试重连... (${this.reconnectAttempts}/${this.maxReconnectAttempts}), ${delay}ms后重连`)
      
      setTimeout(() => {
        if (!this.isManualClose) {
          console.log(`第${this.reconnectAttempts}次重连尝试开始`)
          this.connect()
        }
      }, delay)
    } else {
      console.error('达到最大重连次数，停止重连')
      this.connectionStatus = 'failed'
      
      // 显示详细的失败信息
      uni.showModal({
        title: '连接失败',
        content: `无法连接到聊天服务器\n\n请检查：\n1. 后端服务是否正常运行\n2. 网络连接是否正常\n3. 服务器地址: localhost:6002`,
        showCancel: true,
        cancelText: '取消',
        confirmText: '重新连接',
        success: (res) => {
          if (res.confirm) {
            // 重置重连计数器并重新尝试
            this.reconnectAttempts = 0
            this.connectionStatus = 'disconnected'
            setTimeout(() => this.connect(), 1000)
          }
        }
      })
    }
  }

  /**
   * 启动心跳
   */
  startHeartbeat() {
    this.stopHeartbeat() // 先停止之前的心跳
    
    this.heartbeatInterval = setInterval(() => {
      if (this.ws && this.ws.readyState === WebSocket.OPEN) {
        this.ws.send('ping')
      }
    }, this.heartbeatTimeout)
  }

  /**
   * 停止心跳
   */
  stopHeartbeat() {
    if (this.heartbeatInterval) {
      clearInterval(this.heartbeatInterval)
      this.heartbeatInterval = null
    }
  }

  /**
   * 发送私聊消息
   * @param {string} toName - 接收者用户名
   * @param {string} message - 消息内容
   * @param {string} messageType - 消息类型（默认text）
   * @param {number} toUserId - 目标用户ID（可选，如果提供则不需要查询）
   */
  async sendMessage(toName, message, messageType = 'text', toUserId = null) {
    if (!toName || !message) {
      console.warn('消息参数不完整')
      return false
    }

    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      try {
        // 获取当前用户ID
        const fromId = getCurrentUserId()
        if (!fromId) {
          console.error('无法获取当前用户ID')
          return false
        }

        // 获取目标用户ID
        let toId = toUserId

        // 如果没有传递目标用户ID，则通过API查询
        if (!toId) {
          try {
            const userInfoResponse = await userApi.getUserInfoByUsername(toName)
            if (userInfoResponse && userInfoResponse.data && userInfoResponse.data.id) {
              toId = userInfoResponse.data.id
            } else {
              console.error('无法获取目标用户ID，用户名:', toName)
              return false
            }
          } catch (error) {
            console.error('获取目标用户信息失败:', error)
            return false
          }
        }

        const messageData = {
          toName: toName,
          toId: toId,
          fromId: fromId,
          message: message,
          messageType: messageType,
          chatType: 'private',
          timestamp: Date.now()
        }

        this.ws.send(JSON.stringify(messageData))
        console.log('私聊消息发送成功:', messageData)
        return true
      } catch (error) {
        console.error('发送私聊消息失败:', error)
        return false
      }
    } else {
      console.error('WebSocket未连接，状态:', this.getConnectionStatusText())

      // 尝试重连
      if (!this.isManualClose && this.connectionStatus !== 'connecting') {
        this.connect()
      }

      return false
    }
  }

  /**
   * 发送群聊消息
   * @param {number} groupId - 群组ID
   * @param {string} message - 消息内容
   * @param {string} messageType - 消息类型（默认text）
   */
  sendGroupMessage(groupId, message, messageType = 'text') {
    if (!groupId || !message) {
      console.warn('群聊消息参数不完整')
      return false
    }

    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      const messageData = {
        groupId: groupId,
        message: message,
        messageType: messageType,
        chatType: 'group',
        timestamp: Date.now()
      }

      try {
        this.ws.send(JSON.stringify(messageData))
        console.log('群聊消息发送成功:', messageData)
        return true
      } catch (error) {
        console.error('发送群聊消息失败:', error)
        return false
      }
    } else {
      console.error('WebSocket未连接，状态:', this.getConnectionStatusText())

      // 尝试重连
      if (!this.isManualClose && this.connectionStatus !== 'connecting') {
        this.connect()
      }

      return false
    }
  }

  /**
   * 发送图片消息（私聊）
   * @param {string} toName - 接收者用户名
   * @param {Object} imageData - 图片消息数据
   * @param {number} toId - 接收者用户ID
   */
  sendImageMessage(toName, imageData, toId = null) {
    if (!toName || !imageData || !imageData.message) {
      console.warn('图片消息参数不完整')
      return false
    }

    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      // 获取当前用户ID
      const currentUserId = getCurrentUserId()

      const messageData = {
        fromId: currentUserId,
        toId: toId,
        toName: toName,
        message: imageData.message,
        messageType: 'image',
        chatType: 'private',
        fileSize: imageData.fileSize,
        originalFilename: imageData.originalFilename,
        timestamp: Date.now()
      }

      try {
        this.ws.send(JSON.stringify(messageData))
        console.log('私聊图片消息发送成功:', messageData)
        return true
      } catch (error) {
        console.error('发送私聊图片消息失败:', error)
        return false
      }
    } else {
      console.error('WebSocket未连接，状态:', this.getConnectionStatusText())
      return false
    }
  }

  /**
   * 发送视频消息（私聊）
   * @param {string} toName - 接收者用户名
   * @param {Object} videoData - 视频消息数据
   * @param {number} toId - 接收者用户ID
   */
  sendVideoMessage(toName, videoData, toId = null) {
    if (!toName || !videoData || !videoData.message) {
      console.warn('视频消息参数不完整')
      return false
    }

    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      // 获取当前用户ID
      const currentUserId = getCurrentUserId()

      const messageData = {
        fromId: currentUserId,
        toId: toId,
        toName: toName,
        message: videoData.message,
        messageType: 'video',
        chatType: 'private',
        fileSize: videoData.fileSize,
        originalFilename: videoData.originalFilename,
        videoDuration: videoData.videoDuration,
        videoWidth: videoData.videoWidth,
        videoHeight: videoData.videoHeight,
        videoCoverUrl: videoData.videoCoverUrl,
        timestamp: Date.now()
      }

      try {
        this.ws.send(JSON.stringify(messageData))
        console.log('私聊视频消息发送成功:', messageData)
        return true
      } catch (error) {
        console.error('发送私聊视频消息失败:', error)
        return false
      }
    } else {
      console.error('WebSocket未连接，状态:', this.getConnectionStatusText())
      return false
    }
  }

  /**
   * 发送图片消息（群聊）
   * @param {number} groupId - 群组ID
   * @param {Object} imageData - 图片消息数据
   */
  sendGroupImageMessage(groupId, imageData) {
    if (!groupId || !imageData || !imageData.message) {
      console.warn('群聊图片消息参数不完整')
      return false
    }

    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      // 获取当前用户ID
      const currentUserId = getCurrentUserId()

      const messageData = {
        fromId: currentUserId,
        groupId: groupId,
        message: imageData.message,
        messageType: 'image',
        chatType: 'group',
        fileSize: imageData.fileSize,
        originalFilename: imageData.originalFilename,
        timestamp: Date.now()
      }

      try {
        this.ws.send(JSON.stringify(messageData))
        console.log('群聊图片消息发送成功:', messageData)
        return true
      } catch (error) {
        console.error('发送群聊图片消息失败:', error)
        return false
      }
    } else {
      console.error('WebSocket未连接，状态:', this.getConnectionStatusText())
      return false
    }
  }

  /**
   * 发送视频消息（群聊）
   * @param {number} groupId - 群组ID
   * @param {Object} videoData - 视频消息数据
   */
  sendGroupVideoMessage(groupId, videoData) {
    if (!groupId || !videoData || !videoData.message) {
      console.warn('群聊视频消息参数不完整')
      return false
    }

    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      // 获取当前用户ID
      const currentUserId = getCurrentUserId()

      const messageData = {
        fromId: currentUserId,
        groupId: groupId,
        message: videoData.message,
        messageType: 'video',
        chatType: 'group',
        fileSize: videoData.fileSize,
        originalFilename: videoData.originalFilename,
        videoDuration: videoData.videoDuration,
        videoWidth: videoData.videoWidth,
        videoHeight: videoData.videoHeight,
        videoCoverUrl: videoData.videoCoverUrl,
        timestamp: Date.now()
      }

      try {
        this.ws.send(JSON.stringify(messageData))
        console.log('群聊视频消息发送成功:', messageData)
        return true
      } catch (error) {
        console.error('发送群聊视频消息失败:', error)
        return false
      }
    } else {
      console.error('WebSocket未连接，状态:', this.getConnectionStatusText())
      return false
    }
  }

  /**
   * 处理接收到的消息
   * @param {Object} data - 消息数据
   */
  handleMessage(data) {
    // 通知所有消息处理器
    this.messageHandlers.forEach(handler => {
      try {
        handler(data)
      } catch (error) {
        console.error('消息处理器错误:', error)
      }
    })
  }

  /**
   * 添加消息处理器
   * @param {Function} handler - 消息处理函数
   */
  addMessageHandler(handler) {
    this.messageHandlers.add(handler)
  }

  /**
   * 移除消息处理器
   * @param {Function} handler - 消息处理函数
   */
  removeMessageHandler(handler) {
    this.messageHandlers.delete(handler)
  }

  /**
   * 连接成功回调
   */
  onConnected() {
    // 可以在这里处理连接成功后的逻辑
    // 比如更新UI状态等
  }

  /**
   * 关闭连接
   */
  close() {
    this.isManualClose = true
    this.stopHeartbeat()
    
    if (this.ws) {
      try {
        this.ws.close()
      } catch (error) {
        console.error('关闭 WebSocket 失败:', error)
      } finally {
        this.ws = null
        this.connectionStatus = 'disconnected'
      }
    }
  }

  /**
   * 重新连接
   */
  reconnect() {
    this.isManualClose = false
    this.reconnectAttempts = 0
    this.close()
    
    setTimeout(() => {
      this.connect()
    }, 1000)
  }

  /**
   * 获取连接状态
   */
  getReadyState() {
    return this.ws ? this.ws.readyState : WebSocket.CLOSED
  }

  /**
   * 是否已连接
   */
  isConnected() {
    return this.ws && this.ws.readyState === WebSocket.OPEN
  }

  /**
   * 获取连接状态文本
   */
  getConnectionStatusText() {
    switch (this.connectionStatus) {
      case 'connected': return '已连接'
      case 'connecting': return '连接中'
      case 'reconnecting': return '重连中'
      case 'disconnected': return '已断开'
      case 'error': return '连接错误'
      case 'failed': return '连接失败'
      default: return '未知状态'
    }
  }

  /**
   * 获取连接状态
   */
  getConnectionStatus() {
    return this.connectionStatus
  }

  /**
   * 更新在线用户列表
   * @param {Array} userList - 在线用户列表
   */
  updateOnlineUsers(userList) {
    const oldOnlineUsers = new Set(this.onlineUsers)
    this.onlineUsers = new Set(userList)

    console.log('在线用户列表更新:', userList)

    // 通知在线状态变化处理器
    this.onlineStatusHandlers.forEach(handler => {
      try {
        handler(this.onlineUsers, oldOnlineUsers)
      } catch (error) {
        console.error('在线状态处理器错误:', error)
      }
    })
  }

  /**
   * 检查用户是否在线
   * @param {string} username - 用户名
   * @returns {boolean} 是否在线
   */
  isUserOnline(username) {
    return this.onlineUsers.has(username)
  }

  /**
   * 获取在线用户列表
   * @returns {Set} 在线用户集合
   */
  getOnlineUsers() {
    return new Set(this.onlineUsers)
  }

  /**
   * 添加在线状态变化处理器
   * @param {Function} handler - 处理函数
   */
  addOnlineStatusHandler(handler) {
    this.onlineStatusHandlers.add(handler)
  }

  /**
   * 移除在线状态变化处理器
   * @param {Function} handler - 处理函数
   */
  removeOnlineStatusHandler(handler) {
    this.onlineStatusHandlers.delete(handler)
  }
  
  /**
   * 获取详细的连接信息用于调试
   */
  getDebugInfo() {
    return {
      url: this.url,
      connectionStatus: this.connectionStatus,
      readyState: this.ws ? this.ws.readyState : 'null',
      readyStateText: this.ws ? this.getReadyStateText(this.ws.readyState) : 'WebSocket未初始化',
      reconnectAttempts: this.reconnectAttempts,
      maxReconnectAttempts: this.maxReconnectAttempts,
      isManualClose: this.isManualClose,
      messageHandlersCount: this.messageHandlers.size
    }
  }
  
  /**
   * 获取WebSocket状态文本
   */
  getReadyStateText(readyState) {
    switch (readyState) {
      case WebSocket.CONNECTING: return 'CONNECTING(连接中)'
      case WebSocket.OPEN: return 'OPEN(已连接)'
      case WebSocket.CLOSING: return 'CLOSING(关闭中)'
      case WebSocket.CLOSED: return 'CLOSED(已关闭)'
      default: return `UNKNOWN(${readyState})`
    }
  }

  /**
   * 强制重连
   */
  forceReconnect() {
    console.log('强制重连WebSocket...')
    this.isManualClose = false
    this.reconnectAttempts = 0
    this.disconnect()
    setTimeout(() => {
      this.connect()
    }, 1000)
  }

  /**
   * 检查连接健康状态
   */
  checkConnectionHealth() {
    if (!this.ws) {
      console.log('WebSocket对象不存在')
      return false
    }

    const readyState = this.ws.readyState
    console.log('WebSocket状态:', this.getReadyStateText(readyState))

    if (readyState === WebSocket.OPEN) {
      // 发送心跳测试连接
      try {
        this.ws.send('ping')
        console.log('心跳测试发送成功')
        return true
      } catch (error) {
        console.error('心跳测试失败:', error)
        return false
      }
    }

    return false
  }
}

// 创建全局实例
const chatWebSocket = new ChatWebSocket()

// 自动连接（如果用户已登录）
const autoConnect = () => {
  const userInfo = uni.getStorageSync('userInfo')
  if (userInfo && (userInfo.username || userInfo.nickname)) {
    console.log('自动连接WebSocket...')
    setTimeout(() => {
      chatWebSocket.connect()
    }, 1000) // 延迟1秒连接，确保页面加载完成
  }
}

// 检查uni.ready是否可用
if (typeof uni !== 'undefined' && typeof uni.ready === 'function') {
  uni.ready(autoConnect)
} else {
  // 如果uni.ready不可用，直接执行
  setTimeout(autoConnect, 2000)
}

export default chatWebSocket